module nco_psk (
           input wire clk,
           input wire rst_n,
           input wire din,
           input wire din_valid,
           input wire [31: 0] fcw,
           input wire [31: 0] phase_offset,
           input wire load,
           output wire [14: 0] lut_addr,
           input wire [11: 0] lut_data,
           output wire [11: 0] out,
           output wire out_valid
       );

// 寄存器组
reg [31: 0] phase_reg;
reg [31: 0] freq_reg;
reg [11: 0] out_reg;

// 缓冲寄存器组
reg [1: 0] din_valid_buf;
reg [1: 0] din_buf;
wire din_bfd, din_valid_bfd;

// 缓冲寄存器接口
wire [31: 0] addr;
assign din_bfd = din_buf[2];
assign din_valid_bfd = din_valid_buf[1];

// 地址接口
assign addr = phase_reg + freq_reg + ((din_buf[1]) ? phase_offset : 0);
assign lut_addr = addr[31: 17];

// 输出接口
assign out = (freq_reg != 0 && din_valid_bfd) ? out_reg : 0;
assign out_valid = (freq_reg != 0 && din_valid_bfd) ? 1 : 0;

// 时序缓冲块
always @(posedge clk) begin
    if (!rst_n) begin
        din_valid_buf <= 0;
        din_buf <= 0;
    end else begin
        din_buf <= din_buf << 1;
        din_buf[0] <= din;
        din_valid_buf <= din_valid_buf << 1;
        din_valid_buf[0] <= din_valid;
    end
end

// 相位递增模块
always @(posedge clk) begin
    if (!rst_n) begin
        phase_reg <= 0;
        freq_reg <= 0;
        out_reg <= 0;
    end else begin
        if (din_valid_bfd) begin
            out_reg <= lut_data;
            phase_reg <= phase_reg + freq_reg;
        end else;
        if (load) begin
            freq_reg <= fcw;
        end else ;
    end
end

endmodule
